package ar.com.ford.it.fullEconomics.logic;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Collection;
import ar.com.ford.it.fullEconomics.FullEconomicsPrs;
import ar.com.ford.it.fullEconomics.exception.FullEconomicsException;
import ar.com.ford.it.fullEconomics.persistence.dao.LogDao;
import ar.com.ford.it.fullEconomics.persistence.dao.UsageDao;
import ar.com.ford.it.fullEconomics.persistence.dto.Ncas012VehicleVw;
import ar.com.ford.it.fullEconomics.persistence.dto.Ncas104SfiVw;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesg01Plant;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp01Part;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesp07Usage;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesx03Intflog;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesx04Intflevent;
import ar.com.ford.it.fullEconomics.struct.CounterStruct;
import ar.com.ford.it.fullEconomics.util.FullEconomicsDateUtil;
import ar.com.ford.it.fullEconomics.wslx.FullEconomicsWslxUser;
import ar.com.ford.it.webengine.persistence.PersistenceUtil;
import com.ford.it.logging.ILogger;
import com.ford.it.logging.Level;
import com.ford.it.logging.LogFactory;
import com.ford.it.persistence.PersistenceException;

public class UsageLogic {
    private static final String CLASS_NAME = UsageLogic.class.getName();

    private static final ILogger log = LogFactory.getInstance().getLogger(
            CLASS_NAME);

    /**
     * 
     * @param supplier
     * @param user
     * @throws FullEconomicsException
     */
    public void createUsage(Teesp07Usage usage, FullEconomicsWslxUser user)
            throws FullEconomicsException {
        String METHOD_NAME = "createUsage";
        log.entering(CLASS_NAME, METHOD_NAME);
        UsageDao dao = new UsageDao();

        try {
            PersistenceUtil.newTransaction();
            usage.setEesp07PlantCodeC(user.getTeesg01Plant());
            usage.setEesp07LastUpdtUserC(user.getId());
            usage.setEesp07LastUpdtS(new Timestamp(System.currentTimeMillis()));
            usage.setEesp07CreateUserC(user.getId());
            usage.setEesp07CreateS(new Timestamp(System.currentTimeMillis()));

            dao.createUsage(usage);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log
                    .logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                            "createSupplier", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Supplier.CREATE);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);

    }

    public void updateUsage(Teesp07Usage usage, FullEconomicsWslxUser user)
            throws FullEconomicsException {
        String METHOD_NAME = "updateUsage";
        log.entering(CLASS_NAME, METHOD_NAME);
        UsageDao dao = new UsageDao();
        Teesp07Usage workingCopy = null;
        try {
            PersistenceUtil.newTransaction();
            PersistenceUtil.getPersistenceManager().clearCache();
            workingCopy = dao.getUsageByUpdate(usage);
            if (workingCopy == null)
                throw new FullEconomicsException(new Exception());
            workingCopy.setEesp07UsageOutDateY(usage.getEesp07UsageOutDateY());
            workingCopy
                    .setEesp07UsageQuantityQ(usage.getEesp07UsageQuantityQ());
            workingCopy.setEesp07LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            workingCopy.setEesp07LastUpdtUserC(user.getId());
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Update usage exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Usage.CREATEORUPDATE);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    public void deleteUsage(Teesp07Usage usage) throws FullEconomicsException {
        String METHOD_NAME = "deleteUsage";
        log.entering(CLASS_NAME, METHOD_NAME);
        UsageDao dao = new UsageDao();
        try {
            PersistenceUtil.newTransaction();
            dao.deleteUsage(usage);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log
                    .logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                            "deleteSupplier", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Supplier.DELETE);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Valida el SFI y la pieza , existen
     * 
     * @param usage
     * @return msg inf de que datos no son encontrados
     * @throws FullEconomicsException
     */
    public String validatePkUsage(Teesp07Usage usage)
            throws FullEconomicsException {
        String METHOD_NAME = "createSupplier";
        log.entering(CLASS_NAME, METHOD_NAME);
        String result = "";
        
        // Contruyo Pieza a partir de campos clave para poder validar
        // Added by LSPARACI
        Teesp01Part tempPart = new Teesp01Part();
        tempPart.setEesp01PartBaseCodeC(usage.getEesp07PartBaseCodeC());
        tempPart.setEesp01PartClassCodeC(usage.getEesp07PartClassCodeC());
        tempPart.setEesp01PartPrefixCodeC(usage.getEesp07PartPrefixCodeC());
        tempPart.setEesp01PartSuffixCodeC(usage.getEesp07PartSuffixCodeC());
        
        tempPart.setEesp01PlantCodeC(usage.getEesp07PlantCodeC());
        
        // LSPARACI: usage.getTeesp01Part().setEesp01PlantCodeC(usage.getEesp07PlantCodeC());
        //usage.getTeesp01Part().setEesp01PartClassCodeC("F");
        
        try {
            //if ((new PartLogic()).findPartByPk(usage.getTeesp01Part()) == null) {
       // 	if ((new PartLogic()).findPartByPk(tempPart) == null) {
       //         result = "Warning, No se encuentra la pieza = "
       //         	      + tempPart.toString();
        //                + usage.getTeesp01Part().toString();
       //     }
            if ((new SfiLogic()).getSfiByPk(usage.getNcas104SfiVw()) == null) {
                result = "Warning, No search result SFI: "
                        + " Code Vehicle"
                        + usage.getNcas104SfiVw().getCas104VehicleCodeC()
                                .getCas012VehicleCodeC() + " Code Sfi "
                        + usage.getNcas104SfiVw().getCas104SfiCodeC();
            }
        } catch (FullEconomicsException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Find all Economic Value Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Usage.VALIDATESFI);

        }
        return result;

    }

    /**
     * Realiza el insert o la actualizacion utilizado para el proceso BM
     * 
     * @param usage
     * @param userId
     * @return msg que describe si la operacion se realizo con exito
     * @throws FullEconomicsException
     */
    public CounterStruct createOrUpdate(Collection<Teesp07Usage> usages, String userId,
                               Teesx03Intflog logNumber)
            throws FullEconomicsException {
        String METHOD_NAME = "createOrUpdate";
        log.entering(CLASS_NAME, METHOD_NAME);
        Teesp07Usage workingCopy = new Teesp07Usage();
        UsageDao dao = new UsageDao();
        LogProcessLogic logLogic = new LogProcessLogic();
        int countLine = 0;
        int eventSeq = 0;
        CounterStruct counter = new CounterStruct();
        try {
        	
        	LogDao logDao = new LogDao();
        	eventSeq = logDao.getMax(new Teesx04Intflevent(), null, null,"eesx04IevntSequenceK") + 1;

            for (Teesp07Usage usage : usages) {
                countLine++;
                String validate = validatePkUsage(usage);
                if (validate.contains("Error")) {
                    this.bmRollBack(logNumber, userId);
                    logLogic.insertLogIntfLevent(userId, logNumber, "E",
                            validate, countLine,eventSeq++);
                    counter.addError();
                    throw new FullEconomicsException(new Exception());
                } else if (validate.contains("Warning")) {
                    logLogic.insertLogIntfLevent(userId, logNumber, "W",
                            validate, countLine,eventSeq++);
                    counter.addWarning();
                } else {
                    PersistenceUtil.newTransaction();
                    PersistenceUtil.getPersistenceManager().clearCache();
                    workingCopy = dao.getUsageByUpdate(usage);
                    if (workingCopy != null) {
                        // Compruebo que no se halla modificado ninguna pk en
                        // caso que se haya realizado alguna modificacion en 
                    	// la pk se vuelve a crear el registro
                        // Actualizo el Teesp07Usage
                        logLogic.insertLogIntfLevent(userId, logNumber, "U",
                                this.getModificationDescription(workingCopy,
                                        usage), countLine, eventSeq++);
                        workingCopy.setEesp07UsageOutDateY(usage
                                .getEesp07UsageOutDateY());
                        workingCopy.setEesp07UsageQuantityQ(usage
                                .getEesp07UsageQuantityQ());
                        workingCopy.setEesp07LastUpdtUserC(userId);
                        workingCopy.setEesp07LastUpdtS(new Timestamp(System
                                .currentTimeMillis()));
                        workingCopy.setTeesx03Intflog(logNumber);
                        counter.addCount();
                    } else {
                        usage.setTeesx03Intflog(logNumber);
                        FullEconomicsWslxUser user = new FullEconomicsWslxUser(
                                userId);
                        user.setTeesg01Plant(usage.getEesp07PlantCodeC());
                        this.createUsage(usage, user);
                        counter.addCount();
                    }
                    PersistenceUtil.commitTransaction();
                }
            }
        } catch (PersistenceException e) {
            try {
                logLogic.insertLogIntfLevent(userId, logNumber, "E",
                        "Internal error. Proccess canceled", countLine);
                counter.addError();
                this.bmRollBack(logNumber, userId);
            } catch (PersistenceException e1) {
                logLogic.insertLogIntfLevent(userId, logNumber, "E",
                        "RollBack error", countLine);
                counter.addError();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "update Supplier",
                    e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Usage.CREATEORUPDATE);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
        return counter;
    }

    private void bmRollBack(Teesx03Intflog logNumber, String userId)
            throws FullEconomicsException, PersistenceException {
        UsageDao dao = new UsageDao();

        String[] fields = { "teesx03Intflog" };
        Object[] values = { logNumber };
        String[] eventFields = { "teesx03Intflog", "eesx04IevntTypeCodeC" };
        Object[] eventValues = { logNumber, "U" };

        Collection<Teesx04Intflevent> modifs = dao.findAll(
                new Teesx04Intflevent(), eventFields, eventValues);
        for (Teesx04Intflevent event : modifs) {
            Teesp07Usage usage = this.getOriginalUsage(event);
            FullEconomicsWslxUser user = new FullEconomicsWslxUser(userId);
            user.setTeesg01Plant(usage.getEesp07PlantCodeC());
            this.updateUsage(usage, user);
        }

        Collection<Teesp07Usage> usages = dao.findAll(new Teesp07Usage(),
                fields, values);
        for (Teesp07Usage usage : usages)
            this.deleteUsage(usage);

    }

    private String getModificationDescription(Teesp07Usage origUsage,
                                              Teesp07Usage newUsage) {
    	
        // Contruyo Pieza a partir de campos clave parapoder validar
        // Added by LSPARACI
        Teesp01Part tempPart = new Teesp01Part();
        tempPart.setEesp01PartBaseCodeC(origUsage.getEesp07PartBaseCodeC());
        tempPart.setEesp01PartClassCodeC(origUsage.getEesp07PartClassCodeC());
        tempPart.setEesp01PartPrefixCodeC(origUsage.getEesp07PartPrefixCodeC());
        tempPart.setEesp01PartSuffixCodeC(origUsage.getEesp07PartSuffixCodeC());
        
        tempPart.setEesp01PlantCodeC(origUsage.getEesp07PlantCodeC());
        
        // end Added by LSPARACI
    	
    	
        String desc = "Uso modificado: Planta="
                + origUsage.getEesp07PlantCodeC().getEesg01PlantCodeC()
                + "; Linea="
                + origUsage.getNcas104SfiVw().getCas104VehicleCodeC()
                        .getCas012VehicleCodeC()
                + "; SFI="
                + origUsage.getNcas104SfiVw().getCas104SfiCodeC()
                + "; Pieza="
                + tempPart.toString()
                //+ origUsage.getTeesp01Part().toString()
                + "; Fecha inicio="
                + FullEconomicsDateUtil.format(origUsage
                        .getEesp07UsageInDateY())
                + ". Se cambio: Cantidad="
                + origUsage.getEesp07UsageQuantityQ()
                + " por "
                + newUsage.getEesp07UsageQuantityQ()
                + "; Fecha fin="
                + FullEconomicsDateUtil.format(origUsage
                        .getEesp07UsageOutDateY())
                + " por "
                + FullEconomicsDateUtil.format(newUsage
                        .getEesp07UsageOutDateY()) + ".";
        return desc;
    }

    private Teesp07Usage getOriginalUsage(Teesx04Intflevent event) {
        Teesp07Usage usage = new Teesp07Usage();
        Ncas012VehicleVw line = new Ncas012VehicleVw();
        Ncas104SfiVw sfi = new Ncas104SfiVw();
        Teesg01Plant plant = new Teesg01Plant();
        Teesp01Part part = new Teesp01Part();
        String desc = event.getEesx04IevntMessageDescripX();
        int plantIndex = desc.indexOf("Planta");
        int lineIndex = desc.indexOf("Linea");
        int sfiIndex = desc.indexOf("SFI");
        int partIndex = desc.indexOf("Pieza");
        int inDateIndex = desc.indexOf("Fecha inicio");
        int quantityIndex = desc.indexOf("Cantidad");
        int endQuantityIndex = desc.indexOf(" por ", quantityIndex);
        int endDateIndex = desc.indexOf("Fecha fin");

        String plantCode = desc.substring(plantIndex + 7, lineIndex - 2);
        String lineCode = desc.substring(lineIndex + 6, sfiIndex - 2);
        String sfiCode = desc.substring(sfiIndex + 4, partIndex - 2);
        String[] partCodes = desc.substring(partIndex + 8, inDateIndex - 2)
                .split("-");
        String inDate = desc.substring(inDateIndex + 13, inDateIndex + 23);
        String quantity = desc.substring(quantityIndex + 9, endQuantityIndex);
        String endDate = desc.substring(endDateIndex + 10, endDateIndex + 20);

        plant.setEesg01PlantCodeC(plantCode);
        line.setCas012VehicleCodeC(lineCode);
        sfi.setCas104SfiCodeC(sfiCode);
        sfi.setCas104VehicleCodeC(line);
        part.setEesp01PlantCodeC(plant);
        part.setEesp01PartClassCodeC("F");
        part.setEesp01PartPrefixCodeC(partCodes[0]);
        part.setEesp01PartBaseCodeC(partCodes[1]);
        part.setEesp01PartSuffixCodeC(partCodes[2]);
        usage.setEesp07PlantCodeC(plant);
        usage.setNcas104SfiVw(sfi);
        
        // Modified by LSPARACI
        //usage.setTeesp01Part(part);
        usage.setEesp07PartBaseCodeC(part.getEesp01PartBaseCodeC());
        usage.setEesp07PartClassCodeC(part.getEesp01PartClassCodeC());
        usage.setEesp07PartPrefixCodeC(part.getEesp01PartPrefixCodeC());
        usage.setEesp07PartSuffixCodeC(part.getEesp01PartSuffixCodeC());
        // end Modification LSPARACI
        
        usage.setEesp07UsageInDateY(new Timestamp(FullEconomicsDateUtil.format(
                inDate).getTimeInMillis()));
        usage.setEesp07UsageOutDateY(new Timestamp(FullEconomicsDateUtil
                .format(endDate).getTimeInMillis()));
        usage.setEesp07UsageQuantityQ(new BigDecimal(quantity));

        return usage;
    }
}
